home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
- #include <stdlib.h>
- #include <iostream.h>
- #include "titillat.h"
- #include "plot3d.h"
-
- #ifndef TRUE
- #define TRUE -1
- #endif
- #ifndef FALSE
- #define FALSE 0
- #endif
-
- typedef struct
- {
- int x;
- int y;
- } box_rec;
-
- plot3d::plot3d()
- {
- prime_array_allocated=FALSE;
- plot_prepared=FALSE;
- }
-
- plot3d::~plot3d()
- {
- if (prime_array_allocated)
- delete prime_array;
- }
-
- int plot3d::prepare_plot(
- double (*f)(double,double),
- double x_min,
- double x_max,
- double y_min,
- double y_max,
- int (*external_to_plot)(double,double),
- int (*red)(double,double),
- int x_division_count,
- int y_division_count,
- double rotation_in_degrees,
- double tilt_in_degrees,
- double light_x,
- double light_y,
- double light_z)
- // This function prepares a plot for generation. If returns TRUE if
- // and only if it is successful. If it is successful, "plot" may be called
- // to actually generate the plot. Its parameters are as follow:
- //
- // f -- z=f(x,y), the function to be plotted. Before the plot is
- // tilted or rotated, the z-axis runs from the bottom to the top of the
- // display, the y-axis runs from the left to the right of the display,
- // and the x-axis runs out of the display.
- //
- // x_min -- the minimum value of x to be plotted.
- //
- // x_max -- the maximum value of x to be plotted.
- //
- // y_min -- the minimum value of y to be plotted.
- //
- // y_max -- the maximum value of y to be plotted.
- //
- // external_to_plot -- a function that returns TRUE if and only if a
- // point should be omitted from the plot.
- //
- // red -- a function that returns TRUE if and only if a point should
- // be flagged for highlighting. A point should be so flagged only if it
- // can be seen in the final plot.
- //
- // x_division_count -- the number of x divisions to be used in
- // constructing the plot. At least two must be specified.
- //
- // y_division_count -- the number of y divisions to be used in
- // constructing the plot. At least two must be specified.
- //
- // rotation_in_degrees -- rotation (degrees) about an axis parallel to
- // the z-axis and through the center of the surface.
- //
- // tilt_in_degrees -- tilt (degrees) about an axis through the center
- // of the surface and parallel to a line from the lower left hand corner of
- // the display to the lower right hand corner of the display. The plot is
- // tilted after it is rotated.
- //
- // (light_x,light_y,light_z) -- a vector pointing to the light source
- // (at infinity). The light source remains fixed while the plot is rotated
- // or tilted.
- {
- int display_ready;
- prime_rec initialized_prime_rec;
- int result;
- int x_byte_num;
-
- plot_prepared=FALSE;
- if (prime_array_allocated)
- {
- delete prime_array;
- prime_array_allocated=FALSE;
- }
- num_x_divisions=x_division_count;
- num_y_divisions=y_division_count;
- num_primes=(long) num_x_divisions;
- num_primes*=((long) num_y_divisions);
- // Number of quadrilaterals composing the plot.
- initialized_prime_rec.base_z=(unsigned char) '\0';
- initialized_prime_rec.color=(unsigned char) '\0';
- initialized_prime_rec.x=(float) 0.0;
- initialized_prime_rec.y=(float) 0.0;
- initialized_prime_rec.z=(float) 0.0;
- initialized_prime_rec.x_division_index=0;
- initialized_prime_rec.y_division_index=0;
- prime_array=new varray<prime_rec>(initialized_prime_rec,num_primes,5);
- // Virtual array of quadrilaterals composing the plot.
- if (prime_array_allocated=(prime_array->allocated()))
- {
- titillator_ptr=new titillator;
- rotation=rotation_in_degrees;
- tilt=tilt_in_degrees;
- light.x=light_x;
- light.y=light_y;
- light.z=light_z;
- evaluate_and_transform(f,x_min,x_max,y_min,y_max,
- num_x_divisions,num_y_divisions,rotation,tilt,
- external_to_plot,red);
- // Compute the vertices, etc. of the quadrilaterals composing the
- // plot.
- shade();
- // Compute the shade of gray for each quadrilateral composing the
- // plot.
- adjust_perspective();
- // Force parallel lines running away from the viewer to converge at
- // the horizon.
- sort_back_to_front();
- plot_prepared=TRUE;
- delete titillator_ptr;
- display_ready=display_initialized();
- // Do whatever is necessary to prepare the display.
- }
- return (prime_array_allocated & display_ready);
- }
-
- void plot3d::evaluate_and_transform(
- double (*f)(double,double),
- double x_min,
- double x_max,
- double y_min,
- double y_max,
- int num_x_divisions,
- int num_y_divisions,
- double rotation,
- double tilt,
- int (*external_to_plot)(double,double),
- int (*red)(double,double))
- // Compute the vertices, etc. for each quadrilateral composing the plot.
- {
- double cos_rotation;
- double cos_tilt;
- double degrees_per_radian;
- double magnitude;
- prime_rec *prime;
- long prime_num;
- double radians;
- double sin_rotation;
- double sin_tilt;
- double tem_x;
- double tem_y;
- double tem_z;
- double x;
- double x_delta;
- int x_division_num;
- double x_rotated;
- double y;
- double y_delta;
- int y_division_num;
- double z;
-
- degrees_per_radian=45.0/atan(1.0);
- radians=tilt/degrees_per_radian;
- cos_tilt=cos(radians);
- sin_tilt=sin(radians);
- radians=rotation/degrees_per_radian;
- cos_rotation=cos(radians);
- sin_rotation=sin(radians);
- z=f(x_min,y_min);
- x_rotated=x_min*cos_rotation+y_min*sin_rotation;
- y_prime_min=-x_min*sin_rotation+y_min*cos_rotation;
- z_prime_min=-x_rotated*sin_tilt+z*cos_tilt;
- y_prime_max=y_prime_min;
- z_prime_max=z_prime_min;
- x_prime_max=x_rotated*cos_tilt+z*sin_tilt;
- x_delta=(double) (num_x_divisions-1);
- x_delta=(x_max-x_min)/x_delta;
- y_delta=(double) (num_y_divisions-1);
- y_delta=(y_max-y_min)/y_delta;
- x=x_min;
- prime_num=(long) 0;
- for (x_division_num=0; x_division_num < num_x_divisions; x_division_num++)
- {
- titillator_ptr->titillate();
- y=y_min;
- for (y_division_num=0; y_division_num < num_y_divisions;
- y_division_num++)
- {
- z=f(x,y);
- prime=prime_array->vm_ptr(prime_num);
- if (external_to_plot(x,y))
- prime->base_z=(unsigned char) 3;
- else
- if (red(x,y))
- prime->base_z=(unsigned char) 2;
- else
- prime->base_z=(unsigned char) 1;
- prime->x_division_index=x_division_num;
- prime->y_division_index=y_division_num;
- x_rotated=x*cos_rotation+y*sin_rotation;
- tem_y=(-x*sin_rotation+y*cos_rotation);
- prime->y=(float) tem_y;
- tem_x=(x_rotated*cos_tilt+z*sin_tilt);
- prime->x=(float) tem_x;
- tem_z=(-x_rotated*sin_tilt+z*cos_tilt);
- prime->z=(float) tem_z;
- if (tem_x > x_prime_max)
- x_prime_max=tem_x;
- if (tem_y < y_prime_min)
- y_prime_min=tem_y;
- if (tem_y > y_prime_max)
- y_prime_max=tem_y;
- if (tem_z < z_prime_min)
- z_prime_min=tem_z;
- if (tem_z > z_prime_max)
- z_prime_max=tem_z;
- y+=y_delta;
- prime_num++;
- }
- x+=x_delta;
- }
- magnitude=light.x*light.x+light.y*light.y+light.z*light.z;
- magnitude=sqrt(magnitude);
- light.x=light.x/magnitude;
- light.y=light.y/magnitude;
- light.z=light.z/magnitude;
- return;
- }
-
- void plot3d::shade()
- // Compute the shade of gray for each quadrilateral composing the plot.
- {
- double magnitude;
- vertex_rec normal;
- prime_rec *prime;
- long prime_num;
- vertex_rec vertex [4];
- int x_division_num;
- int y_division_num;
-
- color_min=(unsigned char) (NUM_COLORS-1);
- color_max=(unsigned char) '\0';
- prime_num=num_primes;
- for (x_division_num=num_x_divisions-1; x_division_num >= 0;
- --x_division_num)
- {
- titillator_ptr->titillate();
- for (y_division_num=num_y_divisions-1; y_division_num >= 0;
- --y_division_num)
- {
- prime_num--;
- prime=prime_array->vm_ptr(prime_num);
- vertex[0].x=(double) (prime->x);
- vertex[0].y=(double) (prime->y);
- vertex[0].z=(double) (prime->z);
- if (x_division_num < (num_x_divisions-1))
- if (y_division_num < (num_y_divisions-1))
- {
- prime_num+=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[1].x=(double) (prime->x);
- vertex[1].y=(double) (prime->y);
- vertex[1].z=(double) (prime->z);
- prime_num++;
- prime=prime_array->vm_ptr(prime_num);
- vertex[2].x=(double) (prime->x);
- vertex[2].y=(double) (prime->y);
- vertex[2].z=(double) (prime->z);
- prime_num-=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[3].x=(double) (prime->x);
- vertex[3].y=(double) (prime->y);
- vertex[3].z=(double) (prime->z);
- prime_num--;
- }
- else
- {
- prime_num--;
- prime=prime_array->vm_ptr(prime_num);
- vertex[1].x=(double) (prime->x);
- vertex[1].y=(double) (prime->y);
- vertex[1].z=(double) (prime->z);
- prime_num+=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[2].x=(double) (prime->x);
- vertex[2].y=(double) (prime->y);
- vertex[2].z=(double) (prime->z);
- prime_num++;
- prime=prime_array->vm_ptr(prime_num);
- vertex[3].x=(double) (prime->x);
- vertex[3].y=(double) (prime->y);
- vertex[3].z=(double) (prime->z);
- prime_num-=((long) num_y_divisions);
- }
- else
- if (y_division_num < (num_y_divisions-1))
- {
- prime_num++;
- prime=prime_array->vm_ptr(prime_num);
- vertex[1].x=(double) (prime->x);
- vertex[1].y=(double) (prime->y);
- vertex[1].z=(double) (prime->z);
- prime_num-=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[2].x=(double) (prime->x);
- vertex[2].y=(double) (prime->y);
- vertex[2].z=(double) (prime->z);
- prime_num--;
- prime=prime_array->vm_ptr(prime_num);
- vertex[3].x=(double) (prime->x);
- vertex[3].y=(double) (prime->y);
- vertex[3].z=(double) (prime->z);
- prime_num+=((long) num_y_divisions);
- }
- else
- {
- prime_num-=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[1].x=(double) (prime->x);
- vertex[1].y=(double) (prime->y);
- vertex[1].z=(double) (prime->z);
- prime_num--;
- prime=prime_array->vm_ptr(prime_num);
- vertex[2].x=(double) (prime->x);
- vertex[2].y=(double) (prime->y);
- vertex[2].z=(double) (prime->z);
- prime_num+=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[3].x=(double) (prime->x);
- vertex[3].y=(double) (prime->y);
- vertex[3].z=(double) (prime->z);
- prime_num++;
- }
- // Compute the normal to a quadrilateral by averaging the
- // normals to each vertex of the quadrilateral.
- normal.x
- =(vertex[1].y-vertex[0].y)*(vertex[3].z-vertex[0].z)
- -(vertex[3].y-vertex[0].y)*(vertex[1].z-vertex[0].z)
- +(vertex[2].y-vertex[1].y)*(vertex[0].z-vertex[1].z)
- -(vertex[0].y-vertex[1].y)*(vertex[2].z-vertex[1].z)
- +(vertex[3].y-vertex[2].y)*(vertex[1].z-vertex[2].z)
- -(vertex[1].y-vertex[2].y)*(vertex[3].z-vertex[2].z)
- +(vertex[0].y-vertex[3].y)*(vertex[2].z-vertex[3].z)
- -(vertex[2].y-vertex[3].y)*(vertex[0].z-vertex[3].z);
- normal.y
- =(vertex[3].x-vertex[0].x)*(vertex[1].z-vertex[0].z)
- -(vertex[1].x-vertex[0].x)*(vertex[3].z-vertex[0].z)
- +(vertex[0].x-vertex[1].x)*(vertex[2].z-vertex[1].z)
- -(vertex[2].x-vertex[1].x)*(vertex[0].z-vertex[1].z)
- +(vertex[1].x-vertex[2].x)*(vertex[3].z-vertex[2].z)
- -(vertex[3].x-vertex[2].x)*(vertex[1].z-vertex[2].z)
- +(vertex[2].x-vertex[3].x)*(vertex[0].z-vertex[3].z)
- -(vertex[0].x-vertex[3].x)*(vertex[2].z-vertex[3].z);
- normal.z
- =(vertex[1].x-vertex[0].x)*(vertex[3].y-vertex[0].y)
- -(vertex[3].x-vertex[0].x)*(vertex[1].y-vertex[0].y)
- +(vertex[2].x-vertex[1].x)*(vertex[0].y-vertex[1].y)
- -(vertex[0].x-vertex[1].x)*(vertex[2].y-vertex[1].y)
- +(vertex[3].x-vertex[2].x)*(vertex[1].y-vertex[2].y)
- -(vertex[1].x-vertex[2].x)*(vertex[3].y-vertex[2].y)
- +(vertex[0].x-vertex[3].x)*(vertex[2].y-vertex[3].y)
- -(vertex[2].x-vertex[3].x)*(vertex[0].y-vertex[3].y);
- prime=prime_array->vm_ptr(prime_num);
- magnitude
- =sqrt(normal.x*normal.x+normal.y*normal.y+normal.z*normal.z);
- if (magnitude == 0.0)
- {
- color_min=(unsigned char) '\0';
- prime->color=(unsigned char) '\0';
- }
- else
- {
- prime->color
- =(unsigned char) int((double(NUM_COLORS)/2.0)
- *(1.0+(light.x*normal.x+light.y*normal.y
- +light.z*normal.z)/magnitude)); // shadows not absolute
- if (prime->color
- >= (unsigned char) (NUM_COLORS))
- prime->color=(unsigned char) (NUM_COLORS-1);
- if ((prime->color) < color_min)
- color_min=(prime->color);
- if ((prime->color) > color_max)
- color_max=(prime->color);
- }
- }
- }
- return;
- }
-
- void plot3d::adjust_perspective()
- // Make parallel lines running away from the viewer appear to converge at the
- // horizon.
- {
- prime_rec *prime;
- long prime_num;
- double tem;
- vertex_rec vertex [4];
- int x_division_num;
- double x_eye;
- double y_center;
- int y_division_num;
- double z_center;
-
- if ((y_prime_max-y_prime_min) > (z_prime_max-z_prime_min))
- x_eye=1.1*(y_prime_max-y_prime_min)+x_prime_max;
- else
- x_eye=1.1*(z_prime_max-z_prime_min)+x_prime_max;
- if (((y_prime_max-y_prime_min) > (z_prime_max-z_prime_min))
- || (z_prime_max != z_prime_min))
- {
- y_center=(y_prime_max+y_prime_min)/2.0;
- z_center=(z_prime_max+z_prime_min)/2.0;
- prime_num=(long) 0;
- for (x_division_num=0; x_division_num < num_x_divisions;
- x_division_num++)
- {
- titillator_ptr->titillate();
- for (y_division_num=0; y_division_num < num_y_divisions;
- y_division_num++)
- {
- prime=prime_array->vm_ptr(prime_num);
- vertex[0].x=(double) (prime->x);
- vertex[0].y=(double) (prime->y);
- vertex[0].z=(double) (prime->z);
- if (x_division_num < (num_x_divisions-1))
- if (y_division_num < (num_y_divisions-1))
- {
- prime_num+=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[1].x=(double) (prime->x);
- vertex[1].y=(double) (prime->y);
- vertex[1].z=(double) (prime->z);
- prime_num++;
- prime=prime_array->vm_ptr(prime_num);
- vertex[2].x=(double) (prime->x);
- vertex[2].y=(double) (prime->y);
- vertex[2].z=(double) (prime->z);
- prime_num-=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[3].x=(double) (prime->x);
- vertex[3].y=(double) (prime->y);
- vertex[3].z=(double) (prime->z);
- prime_num--;
- }
- else
- {
- prime_num--;
- prime=prime_array->vm_ptr(prime_num);
- vertex[1].x=(double) (prime->x);
- vertex[1].y=(double) (prime->y);
- vertex[1].z=(double) (prime->z);
- prime_num+=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[2].x=(double) (prime->x);
- vertex[2].y=(double) (prime->y);
- vertex[2].z=(double) (prime->z);
- prime_num++;
- prime=prime_array->vm_ptr(prime_num);
- vertex[3].x=(double) (prime->x);
- vertex[3].y=(double) (prime->y);
- vertex[3].z=(double) (prime->z);
- prime_num-=((long) num_y_divisions);
- }
- else
- if (y_division_num < (num_y_divisions-1))
- {
- prime_num++;
- prime=prime_array->vm_ptr(prime_num);
- vertex[1].x=(double) (prime->x);
- vertex[1].y=(double) (prime->y);
- vertex[1].z=(double) (prime->z);
- prime_num-=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[2].x=(double) (prime->x);
- vertex[2].y=(double) (prime->y);
- vertex[2].z=(double) (prime->z);
- prime_num--;
- prime=prime_array->vm_ptr(prime_num);
- vertex[3].x=(double) (prime->x);
- vertex[3].y=(double) (prime->y);
- vertex[3].z=(double) (prime->z);
- prime_num+=((long) num_y_divisions);
- }
- else
- {
- prime_num-=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[1].x=(double) (prime->x);
- vertex[1].y=(double) (prime->y);
- vertex[1].z=(double) (prime->z);
- prime_num--;
- prime=prime_array->vm_ptr(prime_num);
- vertex[2].x=(double) (prime->x);
- vertex[2].y=(double) (prime->y);
- vertex[2].z=(double) (prime->z);
- prime_num+=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[3].x=(double) (prime->x);
- vertex[3].y=(double) (prime->y);
- vertex[3].z=(double) (prime->z);
- prime_num++;
- }
- prime=prime_array->vm_ptr(prime_num);
- tem=y_center
- +(vertex[0].y-y_center)*(x_eye-x_prime_max)
- /(x_eye-vertex[0].x);
- prime->y=(float) tem;
- tem=z_center
- +(vertex[0].z-z_center)*(x_eye-x_prime_max)
- /(x_eye-vertex[0].x);
- prime->z=(float) tem;
- tem=(vertex[0].x+vertex[1].x+vertex[2].x+vertex[3].x)/4.0;
- prime->x=(float) tem;
- prime_num++;
- }
- }
- }
- return;
- }
-
- void plot3d::rearrange(
- long lower_bound,
- long upper_bound,
- long *j)
- {
- long down;
- int finished;
- prime_rec *prime_1;
- prime_rec *prime_2;
- long up;
- float x1;
- int x_division_index1;
- int y_division_index1;
-
- prime_1=prime_array->vm_ptr(lower_bound);
- x1=prime_1->x;
- x_division_index1=prime_1->x_division_index;
- y_division_index1=prime_1->y_division_index;
- *j=lower_bound;
- up=upper_bound;
- down=lower_bound;
- do
- {
- finished=FALSE;
- while (! finished)
- if (up <= down)
- finished=TRUE;
- else
- {
- prime_1=prime_array->vm_ptr(up);
- if (prime_1->x < x1)
- finished=TRUE;
- else
- up--;
- };
- *j=up;
- if (up != down)
- {
- prime_1=prime_array->vm_ptr(down);
- prime_2=prime_array->vm_ptr(up);
- prime_1->x=prime_2->x;
- prime_1->x_division_index=prime_2->x_division_index;
- prime_1->y_division_index=prime_2->y_division_index;
- finished=FALSE;
- while (! finished)
- if (down >= up)
- finished=TRUE;
- else
- {
- prime_1=prime_array->vm_ptr(down);
- if (prime_1->x > x1)
- finished=TRUE;
- else
- down++;
- };
- *j=down;
- if (down != up)
- {
- prime_1=prime_array->vm_ptr(up);
- prime_2=prime_array->vm_ptr(down);
- prime_1->x=prime_2->x;
- prime_1->x_division_index=prime_2->x_division_index;
- prime_1->y_division_index=prime_2->y_division_index;
- }
- }
- }
- while (down != up);
- prime_1=prime_array->vm_ptr(*j);
- prime_1->x=x1;
- prime_1->x_division_index=x_division_index1;
- prime_1->y_division_index=y_division_index1;
- return;
- }
-
- void plot3d::quicksort(
- long lower_bound,
- long upper_bound)
- // Recursive quicksort. According to Knuth, quicksort is suited for
- // virtual memory.
- {
- long j;
-
- if (lower_bound < upper_bound)
- {
- titillator_ptr->titillate();
- rearrange(lower_bound,upper_bound,&j);
- quicksort(lower_bound,j-1l);
- quicksort(j+1l,upper_bound);
- }
- return;
- }
-
- void plot3d::sort_back_to_front()
- // The painter's algorithm is used; items farther from the viewer are drawn
- // earlier.
- {
- quicksort(0l,num_primes-1l);
- return;
- }
-
- int plot3d::plot(
- char *file_name,
- int show_red,
- int titillate,
- double bias)
- // This function returns TRUE if and only if it is successful in generating
- // the 3D plot. It calls "aspect_ratio", "pset", and "write_outfile". Its
- // parameters are as follow:
- //
- // file_name -- the name of the file to which the plot is to be
- // written. For plots on a cathode ray tube, this will usually be "".
- //
- // show_red -- highlight quadrilaterals having each vertex flagged
- // to be highlighted. Since only those quadrilaterals are redrawn,
- // "plot" should not be called with "show_red" set to TRUE until after
- // it has been called with "show_red" set to FALSE.
- //
- // titillate -- TRUE if the user is to be kept amused while the
- // plot is being generated; FALSE otherwise. In general, "titillate"
- // should be TRUE for printers and FALSE for cathode ray tubes.
- //
- // bias -- a positive number used to adjust the contrast.
- //
- // "prepare_plot" must be called before "plot", after which "plot" may be called
- // as many times as desired.
- {
- double box_delta_x;
- double box_delta_y;
- box_rec box [4];
- int box_num_1;
- int box_num_2;
- double box_x_intercept;
- int box_x1;
- int box_x2;
- int box_y_max;
- int box_y_min;
- double box_y_offset;
- int box_y1;
- int color_num;
- double fraction;
- int intercept_count_mod_2;
- int line_x1;
- int line_x2;
- int outside_maze;
- double pixels_per_unit;
- prime_rec *prime;
- long prime_num;
- int red_showing;
- int result;
- int tint;
- vertex_rec vertex [4];
- int x_division_num;
- long x_prime_num;
- int x_prime_num_mod_50;
- int y_division_num;
- double y_offset;
- double y_out_max;
- double z_offset;
- double z_out_max;
-
- if (plot_prepared)
- {
- y_out_max=double(num_x_pixels()-1);
- z_out_max=double(num_y_pixels()-1);
- if (aspect_ratio()*z_out_max*(y_prime_max-y_prime_min)
- > y_out_max*(z_prime_max-z_prime_min))
- {
- pixels_per_unit
- =y_out_max/(aspect_ratio()*(y_prime_max-y_prime_min));
- y_offset=0.0;
- z_offset
- =-(z_out_max-pixels_per_unit*(z_prime_max-z_prime_min))/2.0;
- }
- else
- if (aspect_ratio()*z_out_max*(y_prime_max-y_prime_min)
- < y_out_max*(z_prime_max-z_prime_min))
- {
- pixels_per_unit=z_out_max/(z_prime_max-z_prime_min);
- y_offset=(y_out_max
- -aspect_ratio()*pixels_per_unit*(y_prime_max-y_prime_min))/2.0;
- z_offset=0.0;
- }
- else
- {
- pixels_per_unit=1.0;
- y_offset=y_out_max/2.0;
- z_offset=-z_out_max/2.0;
- };
- if (titillate)
- {
- x_prime_num_mod_50=0;
- titillator_ptr=new titillator;
- }
- for (x_prime_num=0l; x_prime_num < num_primes; x_prime_num++)
- {
- if (titillate)
- {
- x_prime_num_mod_50++;
- if (x_prime_num_mod_50 >= 50)
- {
- x_prime_num_mod_50=0;
- titillator_ptr->titillate();
- }
- }
- prime=prime_array->vm_ptr(x_prime_num);
- x_division_num=prime->x_division_index;
- if (x_division_num < (num_x_divisions-1))
- {
- y_division_num=prime->y_division_index;
- if (y_division_num < (num_y_divisions-1))
- {
- prime_num
- =((long) num_y_divisions)*((long) x_division_num)
- +((long) y_division_num);
- prime=prime_array->vm_ptr(prime_num);
- color_num=(int) (prime->color);
- if (color_num < NUM_COLORS)
- {
- // Adjust contrast.
- fraction=((double) (color_num-color_min))
- /((double) (color_max-color_min));
- if (fraction > 0.0)
- {
- fraction=exp(bias*log(fraction));
- color_num=(int)
- (((double) (LIGHTEST_GRAY-DARKEST_GRAY))
- *fraction
- +((double) DARKEST_GRAY));
- }
- else
- color_num=DARKEST_GRAY;
- }
- vertex[0].y=(double) (prime->y);
- vertex[0].z=(double) (prime->z);
- red_showing=(prime->base_z == (unsigned char) 2);
- outside_maze=(prime->base_z == (unsigned char) 3);
- prime_num+=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[1].y=(double) (prime->y);
- vertex[1].z=(double) (prime->z);
- if (red_showing)
- red_showing=(prime->base_z == (unsigned char) 2);
- if (outside_maze)
- outside_maze=(prime->base_z == (unsigned char) 3);
- prime_num++;
- prime=prime_array->vm_ptr(prime_num);
- vertex[2].y=(double) (prime->y);
- vertex[2].z=(double) (prime->z);
- if (red_showing)
- red_showing=(prime->base_z == (unsigned char) 2);
- if (outside_maze)
- outside_maze=(prime->base_z == (unsigned char) 3);
- prime_num-=((long) num_y_divisions);
- prime=prime_array->vm_ptr(prime_num);
- vertex[3].y=(double) (prime->y);
- vertex[3].z=(double) (prime->z);
- if (red_showing)
- red_showing=(prime->base_z == (unsigned char) 2);
- if (outside_maze)
- outside_maze=(prime->base_z == (unsigned char) 3);
- if (outside_maze)
- color_num=NUM_COLORS+1;
- if ((! show_red) || (red_showing))
- // Plot each point in a quadrilateral.
- {
- if (show_red)
- color_num=NUM_COLORS;
- for (box_num_1=0; box_num_1 < 4; box_num_1++)
- {
- box[box_num_1].x=(int) (y_offset
- +pixels_per_unit*aspect_ratio()
- *(vertex[box_num_1].y-y_prime_min));
- box[box_num_1].y=(int) (z_offset+z_out_max
- -pixels_per_unit
- *(vertex[box_num_1].z-z_prime_min));
- }
- box_y_min=box[0].y;
- box_y_max=box_y_min;
- for (box_num_1=1; box_num_1 < 4; box_num_1++)
- {
- if (box[box_num_1].y < box_y_min)
- box_y_min=box[box_num_1].y;
- if (box[box_num_1].y > box_y_max)
- box_y_max=box[box_num_1].y;
- }
- for (box_y1=box_y_min; box_y1 <= box_y_max;
- ++box_y1)
- {
- intercept_count_mod_2=0;
- box_num_2=1;
- for (box_num_1=0; box_num_1 < 4; ++box_num_1)
- {
- if (box[box_num_1].y >= box_y1)
- {
- if (box_y1 > box[box_num_2].y)
- {
- box_delta_y=(double)
- (box[box_num_2].y
- -box[box_num_1].y);
- box_delta_x=(double)
- (box[box_num_2].x
- -box[box_num_1].x);
- box_y_offset=(double)
- (box_y1-box[box_num_1].y);
- box_x_intercept=(double)
- (box[box_num_1].x);
- box_x1=(int)
- ((box_delta_x*box_y_offset)
- /box_delta_y+box_x_intercept);
- if (intercept_count_mod_2 == 0)
- box_x2=box_x1;
- else
- {
- if (box_x1 < box_x2)
- {
- line_x1=box_x1;
- line_x2=box_x2;
- }
- else
- {
- line_x1=box_x2;
- line_x2=box_x1;
- }
- pset(line_x1,box_y1,
- color_num);
- while (line_x1 < line_x2)
- {
- line_x1++;
- pset(line_x1,box_y1,
- color_num);
- }
- }
- intercept_count_mod_2
- =1-intercept_count_mod_2;
- }
- }
- else
- {
- if (box_y1 <= box[box_num_2].y)
- {
- box_delta_y=(double)
- (box[box_num_2].y
- -box[box_num_1].y);
- box_delta_x=(double)
- (box[box_num_2].x
- -box[box_num_1].x);
- box_y_offset=(double)
- (box_y1-box[box_num_1].y);
- box_x_intercept=(double)
- (box[box_num_1].x);
- box_x1=(int)
- ((box_delta_x*box_y_offset)
- /box_delta_y+box_x_intercept);
- if (intercept_count_mod_2 == 0)
- box_x2=box_x1;
- else
- {
- if (box_x1 < box_x2)
- {
- line_x1=box_x1;
- line_x2=box_x2;
- }
- else
- {
- line_x1=box_x2;
- line_x2=box_x1;
- }
- pset(line_x1,box_y1,
- color_num);
- while (line_x1 < line_x2)
- {
- line_x1++;
- pset(line_x1,box_y1,
- color_num);
- }
- }
- intercept_count_mod_2
- =1-intercept_count_mod_2;
- }
- }
- box_num_2++;
- if (box_num_2 >= 4)
- box_num_2=0;
- }
- }
- }
- }
- }
- }
- if (titillate)
- delete titillator_ptr;
- result=write_outfile(file_name);
- }
- else
- {
- result=FALSE;
- cerr << "Fatal error: attempt to plot before prepared." << '\n';
- }
- return result;
- }
-